package cpoo.globalMotion;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import cpoo.exceptions.MotionException;

public class ReferencedImagePart extends ImagePart {
	private ArrayList<ArrayList<PartialSum>> shiftedSums; 
	
	public ReferencedImagePart(BufferedImage image, Rectangle partBorders, boolean sumCols, int maxImageDisplacement){
		super(image, partBorders, sumCols, maxImageDisplacement);
		shiftedSums = new ArrayList<ArrayList<PartialSum>>();
		int sums[] = null;
		if (sumCols){
			sums = new int[partBorders.width];

			for (int i=0;i<sums.length;i++){
				sums[i] = 0;
			}
			ArrayList<PartialSum> shiftedSum = new ArrayList<PartialSum>();
			for (int i=0; i<sums.length; i++){
				shiftedSum.add(new PartialSum(0, partBorders.height, 0));
			}
			shiftedSums.add(shiftedSum);
			for (int y=partBorders.height-1; y>0; y--){
				for (int x=0; x<partBorders.width; x++){
					sums[x] += this.getIValue(partBorders.x + x,partBorders.y + y);
				}
				shiftedSum = new ArrayList<PartialSum>();
				for (int i=0; i<sums.length; i++){
					shiftedSum.add(new PartialSum(sums[i], y, 0));
				}
				shiftedSums.add(shiftedSum); // uciete z gory
			}
			
			shiftedSums.add(partialSums); // nie przesuniety
			
			int addIndex = shiftedSums.size();
			
			for (int i=0;i<sums.length;i++){
				sums[i] = 0;
			}
			
			for (int y=0; y<partBorders.height-1; y++){
				for (int x=0; x<partBorders.width; x++){
					sums[x] += this.getIValue(partBorders.x + x,partBorders.y + y);
				}
				shiftedSum = new ArrayList<PartialSum>();
				for (int i=0; i<sums.length; i++){
					shiftedSum.add(new PartialSum(sums[i], 0,partBorders.height -1 -y));
				}
				shiftedSums.add(addIndex, shiftedSum); //uciete z dolu
			}
			
			shiftedSum = new ArrayList<PartialSum>();
			for (int i=0; i<sums.length; i++){
				shiftedSum.add(new PartialSum(0, 0,partBorders.height));
			}
			shiftedSums.add(shiftedSum);
		} else {
			sums = new int[partBorders.height];

			for (int i=0;i<sums.length;i++){
				sums[i] = 0;
			}
			
			ArrayList<PartialSum> shiftedSum = new ArrayList<PartialSum>();
			for (int i=0; i<sums.length; i++){
				shiftedSum.add(new PartialSum(0, partBorders.width, 0));
			}
			shiftedSums.add(shiftedSum); // uciete z lewej
			
			for (int x=partBorders.width-1; x>0; x--){
				for (int y=0; y<partBorders.height; y++){
					sums[y] += this.getIValue(partBorders.x + x,partBorders.y + y);
				}
				shiftedSum = new ArrayList<PartialSum>();
				for (int i=0; i<sums.length; i++){
					shiftedSum.add(new PartialSum(sums[i], x, 0));
				}
				shiftedSums.add(shiftedSum); // uciete z lewej
			}
			
			shiftedSums.add(partialSums); // nie przesuniety
			
			int addIndex = shiftedSums.size();
			
			for (int i=0;i<sums.length;i++){
				sums[i] = 0;
			}
			
			for (int x=0; x<partBorders.width-1; x++){
				for (int y=0; y<partBorders.height; y++){
					sums[y] += this.getIValue(partBorders.x + x,partBorders.y + y);
				}
				shiftedSum = new ArrayList<PartialSum>();
				for (int i=0; i<sums.length; i++){
					shiftedSum.add(new PartialSum(sums[i], 0, partBorders.width -1 -x));
				}
				shiftedSums.add(addIndex, shiftedSum); //uciete z prawej
			}
			
			shiftedSum = new ArrayList<PartialSum>();
			for (int i=0; i<sums.length; i++){
				shiftedSum.add(new PartialSum(0, 0,partBorders.width));
			}
			shiftedSums.add(shiftedSum);
		}
	}
	
	private int lastDisplacement = 0;
	
	public double minimumDifferance(ImagePart p2) throws MotionException{
		int displacement = p2.getDisplacement();
		if (lastDisplacement != displacement){
			int index = 0;
			if (sumCols){
				index = displacement + partBorders.height ;
			} else {
				index = displacement + partBorders.width ;
			}
			partialSums = shiftedSums.get(index);
			lastDisplacement = displacement;
		}
		return super.minimumDifferance(p2);
	}
}
